package com.training.java.module1;

import java.util.Scanner;

/**
 * The class provides long division
 * @author Serhey Shevchuk
 *
 */
public class LongDivision {
	/**
	 * The method return, length of integer number
	 * @param number number
	 * @return length of number
	 */
	private int getNumberSize(int number) {
		return Integer.toString(number).length();
	}

	private void getDigitsOfDividend(int dividend, int[] digitsOfDividend) {

        int base = 10;

        for(int i = digitsOfDividend.length-1; dividend != 0; i--){
			digitsOfDividend[i] = dividend % base;
			dividend /= base;
		}
	}

	private int getFirstDividend(int divisor, int[] digitsOfDividend) {

        int firstDividend = 0;

        int base = 10;

		for(int i=0; i<getNumberSize(divisor); i++) {
			firstDividend  = firstDividend * base + digitsOfDividend[i];
		}
		
		return firstDividend;
	}
	/**
	 * The method that return next dividend
	 * @param remainder remainder from previous step
	 * @return next dividend
	 */
	private int getNextDividend(int remainder, int currentDigit, int[] digitsOfDividend) {

        int base = 10;

        return remainder * base + digitsOfDividend[currentDigit];
		
	}

    private void printCalculation(int dividend, int divisor, String listOfCalculationResults){

        System.out.printf(" %d | %d%n", dividend, divisor);
        System.out.printf("%s", listOfCalculationResults);
    }

    /**
     * Converts digits result to string on each iteration of calculation
     * @param currentDividend  dividend on current step
     * @param currentDividendWithoutRemainder dividend on current step without remainder
     * @param iteration number of iteration
     * @return result string on current iteration
     */
    private String getIterationResultString(int currentDividend, int currentDividendWithoutRemainder, int iteration) {
        String iterationResult = "";

        iterationResult += String.format("%"+iteration+"d%n",currentDividend);
        iterationResult += String.format("%"+iteration+"s%d%n----%n", "-", currentDividendWithoutRemainder);

        return iterationResult;

    }

    private String addFinalResultsToString(int remainder, int quotient) {
        String finalResultsString = "";

        finalResultsString += String.format("%d%n", remainder);
        finalResultsString += String.format("%s%d%n", "Quotient:", quotient);

        return finalResultsString;
    }
    /**
     * Division intermediate calculations
     * @param currentDividend dividend on current step
     * @param divisor divisor
     * @param digitsOfDividend digits of dividend on current step
     * @return  String of calculation results
     */
	private String doIntermediateCalculations(int currentDividend, int divisor, int[] digitsOfDividend) {
		String calculationResult = "";
        int remainder = 0;
        int quotient = 0;

        for(int i = getNumberSize(currentDividend); i <= digitsOfDividend.length; i++) {
			int digitOfQuotient = currentDividend / divisor;
            quotient = (quotient * 10) + digitOfQuotient;
			remainder = currentDividend % divisor;
            int currentDividendWithoutRemainder = digitOfQuotient * divisor;
            calculationResult += getIterationResultString(currentDividend, currentDividendWithoutRemainder, i);
			if(i != digitsOfDividend.length) {
				currentDividend = getNextDividend(remainder, i , digitsOfDividend);
			}
		}
        calculationResult += addFinalResultsToString(remainder, quotient);
        return calculationResult;
	}
	
	private void executeLongDivision() {
        int dividend = inputDividend();

        int divisor = inputDivisor();

        int[] digitsOfDividend = new int[getNumberSize(dividend)];

        getDigitsOfDividend(dividend, digitsOfDividend);
		
		int currentDividend = getFirstDividend(divisor, digitsOfDividend);

        printCalculation(dividend, divisor, doIntermediateCalculations(currentDividend, divisor, digitsOfDividend));
		
	}

    private int inputDividend() {
        Scanner inputScanner = new Scanner( System.in );

        System.out.println("Enter the dividend ");

        return inputScanner.nextInt();
    }

    private int inputDivisor() {
        Scanner inputScanner = new Scanner( System.in );
        int divisor;

        while(true){
            System.out.println("Enter the divisor ");
            divisor = inputScanner.nextInt();

            if(divisor != 0) {
                break;
            } else {
                System.out.println("Division by zero is not possible");
            }
        }

        inputScanner.close();
        return divisor;
    }

	public static void main(String[] args) {

        new LongDivision().executeLongDivision();
    }

}
